home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
mondata.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-22
|
10KB
|
411 lines
/* SCCS Id: @(#)mondata.c 3.1 92/11/24 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "eshk.h"
#include "epri.h"
/* These routines provide basic data for any type of monster. */
#ifdef OVL0
boolean
attacktype(ptr, atyp)
register struct permonst *ptr;
register int atyp;
{
int i;
for(i = 0; i < NATTK; i++)
if(ptr->mattk[i].aatyp == atyp) return(TRUE);
return(FALSE);
}
#endif /* OVL0 */
#ifdef OVLB
boolean
poly_when_stoned(ptr)
struct permonst *ptr;
{
return (is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM] &&
!(mons[PM_STONE_GOLEM].geno & G_GENOD)); /* allow G_EXTINCT */
}
boolean
resists_drli(ptr) /* returns TRUE if monster is drain-life resistant */
register struct permonst *ptr;
{
return(is_undead(ptr) || is_demon(ptr) || is_were(ptr));
}
#endif /* OVLB */
#ifdef OVL0
boolean
ranged_attk(ptr) /* returns TRUE if monster can attack at range */
register struct permonst *ptr;
{
register int i, j;
register int atk_mask = (1<<AT_BREA) | (1<<AT_SPIT) | (1<<AT_GAZE);
/* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP) ||
attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE) ||
attacktype(ptr, AT_MAGC));
but that's too slow -dlc
*/
for(i = 0; i < NATTK; i++) {
if((j=ptr->mattk[i].aatyp) >= AT_WEAP || (atk_mask & (1<<j)))
return TRUE;
}
return(FALSE);
}
boolean
hates_silver(ptr)
register struct permonst *ptr;
/* returns TRUE if monster is especially affected by silver weapons */
{
return (is_were(ptr) || ptr->mlet==S_VAMPIRE || is_demon(ptr) ||
ptr == &mons[PM_SHADE] ||
(ptr->mlet==S_IMP && ptr != &mons[PM_TENGU]));
}
#endif /* OVL0 */
#ifdef OVL1
boolean
can_track(ptr) /* returns TRUE if monster can track well */
register struct permonst *ptr;
{
if (uwep && uwep->oartifact == ART_EXCALIBUR)
return TRUE;
else
return(haseyes(ptr));
}
#endif /* OVL1 */
#ifdef OVLB
#if defined(POLYSELF) || defined(MUSE)
boolean
sliparm(ptr) /* creature will slide out of armor */
register struct permonst *ptr;
{
return is_whirly(ptr) || ptr->msize <= MZ_SMALL ||
ptr == &mons[PM_GHOST];
}
boolean
breakarm(ptr) /* creature will break out of armor */
register struct permonst *ptr;
{
return((bigmonst(ptr) || (ptr->msize > MZ_SMALL && !humanoid(ptr))
|| ptr == &mons[PM_MARILITH]) && !sliparm(ptr));
/* Marilith is about the only case of a monster which is otherwise
* humanoid but cannot wear armor (too many arms). Centaurs would
* be another except that they are already accounted for by
* bigmonst.
*/
}
#endif
#endif /* OVLB */
#ifdef OVL1
boolean
sticks(ptr) /* creature sticks other creatures it hits */
register struct permonst *ptr;
{
return(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) ||
attacktype(ptr,AT_HUGS));
}
boolean
dmgtype(ptr, dtyp)
register struct permonst *ptr;
register int dtyp;
{
int i;
for(i = 0; i < NATTK; i++)
if(ptr->mattk[i].adtyp == dtyp) return TRUE;
return FALSE;
}
/* returns the maximum damage a defender can do to the attacker via
* a passive defense */
int
max_passive_dmg(mdef, magr)
register struct monst *mdef, *magr;
{
int i, dmg = 0;
uchar adtyp;
for(i = 0; i < NATTK; i++)
if(mdef->data->mattk[i].aatyp == AT_NONE) {
adtyp = mdef->data->mattk[i].adtyp;
if((adtyp == AD_ACID && !resists_acid(magr->data)) ||
(adtyp == AD_COLD && !resists_cold(magr->data)) ||
(adtyp == AD_FIRE && !resists_fire(magr->data)) ||
(adtyp == AD_ELEC && !resists_elec(magr->data))) {
dmg = mdef->data->mattk[i].damn;
if(!dmg) dmg = mdef->data->mlevel+1;
dmg *= mdef->data->mattk[i].damd;
} else dmg = 0;
return dmg;
}
return 0;
}
#endif /* OVL1 */
#ifdef OVL0
int
monsndx(ptr) /* return an index into the mons array */
struct permonst *ptr;
{
register int i;
if(ptr == &playermon) return(-1);
i = (int)(ptr - &mons[0]);
if(i < 0 || i >= NUMMONS) {
panic("monsndx - could not index monster (%lx)", (long)ptr);
return FALSE; /* will not get here */
}
return(i);
}
#endif /* OVL0 */
#ifdef OVL1
int
name_to_mon(str)
char *str;
{
/* Be careful. We must check the entire string in case it was
* something such as "ettin zombie corpse". The calling routine
* doesn't know about the "corpse" until the monster name has
* already been taken off the front, so we have to be able to
* read the name with extraneous stuff such as "corpse" stuck on
* the end.
* This causes a problem for names which prefix other names such
* as "ettin" on "ettin zombie". In this case we want the _longest_
* name which exists.
* This also permits plurals created by adding suffixes such as 's'
* or 'es'. Other plurals must still be handled explicitly.
*/
register int i;
register int mntmp = -1;
register char *s;
char buf[BUFSZ];
int len, slen;
Strcpy(buf, str);
str = buf;
if (!strncmp(str, "a ", 2)) str += 2;
else if (!strncmp(str, "an ", 3)) str += 3;
/* Some irregular plurals */
if (!strncmpi(str, "incubi", 6)) return PM_INCUBUS;
if (!strncmpi(str, "succubi", 7)) return PM_SUCCUBUS;
if (!strncmpi(str, "violet fungi", 12)) return PM_VIOLET_FUNGUS;
if (!strncmpi(str, "homunculi", 9)) return PM_HOMUNCULUS;
if (!strncmpi(str, "baluchitheria", 13)) return PM_BALUCHITHERIUM;
if (!strncmpi(str, "lurkers above", 13)) return PM_LURKER_ABOVE;
if (!strncmpi(str, "cavemen", 7)) return PM_CAVEMAN;
if (!strncmpi(str, "cavewomen", 9)) return PM_CAVEWOMAN;
if (!strncmpi(str, "zruties", 7)) return PM_ZRUTY;
if (!strncmpi(str, "djinn", 5)) return PM_DJINNI;
if (!strncmpi(str, "mumakil", 7)) return PM_MUMAK;
if ((s = strstri(str, "vortices")) != 0)
Strcpy(s+4, "ex");
/* be careful with "ies"; "priest", "zombies" */
else if ((s = strstri(str, "jellies")) != 0 ||
(s = strstri(str, "mummies")) != 0)
Strcpy(s+4, "y");
/* luckily no monster names end in fe or ve with ves plurals */
else if ((s = strstri(str, "ves")) != 0)
Strcpy(s, "f");
slen = strlen(str);
for (len = 0, i = 0; i < NUMMONS; i++) {
register int m_i_len = strlen(mons[i].mname);
if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
if (m_i_len == slen) return i; /* exact match */
else if (slen > m_i_len &&
(str[m_i_len] == ' ' ||
!strcmpi(&str[m_i_len], "s") ||
!strncmpi(&str[m_i_len], "s ", 2) ||
!strcmpi(&str[m_i_len], "es") ||
!strncmpi(&str[m_i_len], "es ", 3))) {
mntmp = i;
len = m_i_len;
}
}
}
if (mntmp == -1) mntmp = title_to_mon(str, (int *)0, (int *)0);
return mntmp;
}
#endif /* OVL1 */
#ifdef OVLB
#ifdef POLYSELF
boolean
webmaker(ptr) /* creature can spin a web */
register struct permonst *ptr;
{
return (ptr->mlet == S_SPIDER && ptr != &mons[PM_SCORPION]);
}
#endif
#endif /* OVLB */
#ifdef OVL2
/* returns 3 values (0=male, 1=female, 2=none) */
int
gender(mtmp)
register struct monst *mtmp;
{
if (is_neuter(mtmp->data)) return 2;
return mtmp->female;
}
#endif /* OVL2 */
#ifdef OVLB
boolean
levl_follower(mtmp)
register struct monst *mtmp;
{
return (mtmp->mtame || (mtmp->data->mflags2 & M2_STALK) || is_fshk(mtmp)
|| (mtmp->iswiz && !mon_has_amulet(mtmp)));
}
struct permonst *
player_mon()
{
switch (pl_character[0]) {
case 'A': return &mons[PM_ARCHEOLOGIST];
case 'B': return &mons[PM_BARBARIAN];
case 'C': if (flags.female) return &mons[PM_CAVEWOMAN];
else return &mons[PM_CAVEMAN];
case 'E': return &mons[PM_ELF];
case 'H': return &mons[PM_HEALER];
case 'K': return &mons[PM_KNIGHT];
case 'P': if (flags.female) return &mons[PM_PRIESTESS];
else return &mons[PM_PRIEST];
case 'R': return &mons[PM_ROGUE];
case 'S': return &mons[PM_SAMURAI];
#ifdef TOURIST
case 'T': return &mons[PM_TOURIST];
#endif
case 'V': return &mons[PM_VALKYRIE];
case 'W': return &mons[PM_WIZARD];
default: impossible("what are you?");
return &mons[PM_HUMAN];
}
}
const int grownups[][2] = { {PM_LITTLE_DOG, PM_DOG}, {PM_DOG, PM_LARGE_DOG},
{PM_HELL_HOUND_PUP, PM_HELL_HOUND}, {PM_KITTEN, PM_HOUSECAT},
{PM_HOUSECAT, PM_LARGE_CAT}, {PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON},
{PM_KOBOLD, PM_LARGE_KOBOLD}, {PM_LARGE_KOBOLD, PM_KOBOLD_LORD},
{PM_GNOME, PM_GNOME_LORD}, {PM_GNOME_LORD, PM_GNOME_KING},
{PM_DWARF, PM_DWARF_LORD}, {PM_DWARF_LORD, PM_DWARF_KING},
{PM_SMALL_MIMIC, PM_LARGE_MIMIC}, {PM_LARGE_MIMIC, PM_GIANT_MIMIC},
{PM_BAT, PM_GIANT_BAT},
{PM_LICH, PM_DEMILICH}, {PM_DEMILICH, PM_MASTER_LICH},
{PM_OGRE, PM_OGRE_LORD}, {PM_OGRE_LORD, PM_OGRE_KING},
{PM_VAMPIRE, PM_VAMPIRE_LORD},
{PM_BABY_RED_DRAGON, PM_RED_DRAGON},
{PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON},
{PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON},
{PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON},
{PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON},
{PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON},
{PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON},
{PM_RED_NAGA_HATCHLING, PM_RED_NAGA},
{PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA},
{PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA},
{PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA},
{PM_BABY_PURPLE_WORM, PM_PURPLE_WORM},
{PM_BABY_LONG_WORM, PM_LONG_WORM},
#ifdef ARMY
{PM_SOLDIER, PM_SERGEANT},
{PM_SERGEANT, PM_LIEUTENANT},
{PM_LIEUTENANT, PM_CAPTAIN},
#endif
{PM_WATCHMAN, PM_WATCH_CAPTAIN},
{PM_BABY_CROCODILE, PM_CROCODILE},
{-1,-1}
};
int
little_to_big(montype)
int montype;
{
#ifndef AIXPS2_BUG
register int i;
for(i=0; grownups[i][0] >= 0; i++)
if(montype == grownups[i][0]) return grownups[i][1];
return montype;
#else
/* AIX PS/2 C-compiler 1.1.1 optimizer does not like the above for loop,
* and causes segmentation faults at runtime. (The problem does not
* occur if -O is not used.)
* lehtonen@cs.Helsinki.FI (Tapio Lehtonen) 28031990
*/
int i;
int monvalue;
monvalue = montype;
for(i=0; grownups[i][0] >= 0; i++)
if(montype == grownups[i][0]) monvalue = grownups[i][1];
return monvalue;
#endif
}
int
big_to_little(montype)
int montype;
{
register int i;
for(i=0; grownups[i][0] >= 0; i++)
if(montype == grownups[i][1]) return grownups[i][0];
return montype;
}
const char *
locomotion(ptr, def)
const struct permonst *ptr;
const char *def;
{
return (
is_floater(ptr) ? (const char *)"float" :
is_flyer(ptr) ? (const char *)"fly" :
slithy(ptr) ? (const char *)"slither" :
amorphous(ptr) ? (const char *)"ooze" :
nolimbs(ptr) ? (const char *)"crawl" :
def
);
}
#endif /* OVLB */
/*mondata.c*/